/*
 * Copyright 1999-2022 Alibaba Group Holding Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.alibaba.nacos.plugin.datasource.impl.kingbase8;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.alibaba.nacos.plugin.datasource.constants.FieldConstant;
import com.alibaba.nacos.plugin.datasource.constants.TableConstant;
import com.alibaba.nacos.plugin.datasource.mapper.TenantCapacityMapper;
import com.alibaba.nacos.plugin.datasource.model.MapperContext;
import com.alibaba.nacos.plugin.datasource.model.MapperResult;
import com.alibaba.nacos.plugin.datasource.constants.TableConstant;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import static com.alibaba.nacos.plugin.datasource.constants.DefaultConstant.DEFAULT_TENANT_ID;

/**
 * The mysql implementation of TenantCapacityMapper.
 *
 * @author hyx
 **/

public class TenantCapacityMapperByKingbase8 extends AbstractKingbase8Mapper implements TenantCapacityMapper {

    @Override
    public String getTableName() {
        return TableConstant.TENANT_CAPACITY;
    }

    @Override
    public String getFunction(String s) {
        return s;
    }

    @Override
    public MapperResult incrementUsageWithDefaultQuotaLimit(MapperContext context) {
        String sql= "UPDATE tenant_capacity SET usage = usage + 1, gmt_modified = ? WHERE tenant_id = NVL(?,'" + DEFAULT_TENANT_ID
                + "') AND usage <"
                + " ? AND quota = 0";
        String gmtModified = (String)context.getWhereParameter(FieldConstant.GMT_MODIFIED);
        String tenantId = (String)context.getWhereParameter(FieldConstant.TENANT_ID);
        String usage = (String)context.getWhereParameter(FieldConstant.USAGE);
        List<Object> paramList = new ArrayList();
        paramList.add(gmtModified);
        paramList.add(tenantId);
        paramList.add(usage);
        return new MapperResult(sql, paramList);
    }

    @Override
    public MapperResult incrementUsageWithQuotaLimit(MapperContext context) {
        String sql= "UPDATE tenant_capacity SET usage = usage + 1, gmt_modified = ? WHERE tenant_id = NVL(?,'" + DEFAULT_TENANT_ID + "') AND usage < "
                + "quota AND quota != 0";

        String gmtModified = (String)context.getWhereParameter(FieldConstant.GMT_MODIFIED);
        String tenantId = (String)context.getWhereParameter(FieldConstant.TENANT_ID);
        List<Object> paramList = new ArrayList();
        paramList.add(gmtModified);
        paramList.add(tenantId);

        return new MapperResult(sql, paramList);
    }

    @Override
    public MapperResult incrementUsage(MapperContext context) {
        String sql= "UPDATE tenant_capacity SET usage = usage + 1, gmt_modified = ? WHERE tenant_id = NVL(?, '" + DEFAULT_TENANT_ID + "')";

        String gmtModified = (String)context.getWhereParameter(FieldConstant.GMT_MODIFIED);
        String tenantId = (String)context.getWhereParameter(FieldConstant.TENANT_ID);
        List<Object> paramList = new ArrayList();
        paramList.add(gmtModified);
        paramList.add(tenantId);


        return new MapperResult(sql, paramList);
    }

    @Override
    public MapperResult decrementUsage(MapperContext context) {
        String sql= "UPDATE tenant_capacity SET usage = usage - 1, gmt_modified = ? WHERE tenant_id = NVL(?, '" + DEFAULT_TENANT_ID + "') AND usage > 0";
        String gmtModified = (String)context.getWhereParameter(FieldConstant.GMT_MODIFIED);
        String tenantId = (String)context.getWhereParameter(FieldConstant.TENANT_ID);
        List<Object> paramList = new ArrayList();
        paramList.add(gmtModified);
        paramList.add(tenantId);
        return new MapperResult(sql, paramList);
    }

    @Override
    public MapperResult correctUsage(MapperContext context) {
        String gmtModified = (String)context.getWhereParameter(FieldConstant.GMT_MODIFIED);
        String tenantId = (String)context.getWhereParameter(FieldConstant.TENANT_ID);

        List<Object> paramList = new ArrayList();

        paramList.add(tenantId);
        paramList.add(gmtModified);
        paramList.add(tenantId);

        String sql= "UPDATE tenant_capacity SET usage = (SELECT count(*) FROM config_info WHERE tenant_id = NVL(?, '" + DEFAULT_TENANT_ID + "')), "
                + "gmt_modified = ? WHERE tenant_id = NVL(?, '" + DEFAULT_TENANT_ID + "')";

        return new MapperResult(sql, paramList);
    }

    @Override
    public MapperResult getCapacityList4CorrectUsage(MapperContext context) {
        String sql=getDatabaseDialect().getLimitTopSqlWithMark(
                "SELECT id, tenant_id FROM tenant_capacity WHERE id>?");
        long Id = (long)context.getWhereParameter(FieldConstant.ID);
        List<Object> paramList = new ArrayList();
        paramList.add(Id);
        return new MapperResult(sql, paramList);

    }

    @Override
    public MapperResult insertTenantCapacity(MapperContext context) {
        String sql="INSERT INTO tenant_capacity (tenant_id, quota, usage, max_size, max_aggr_count, max_aggr_size, "
                + "gmt_create, gmt_modified) SELECT ?, ?, count(*), ?, ?, ?, ?, ? FROM config_info WHERE tenant_id=NVL(?, '" + DEFAULT_TENANT_ID + "')";

        List<Object> paramList = new ArrayList();

        paramList.add(context.getUpdateParameter(FieldConstant.TENANT_ID));
        paramList.add(context.getUpdateParameter(FieldConstant.QUOTA));

        paramList.add(context.getUpdateParameter(FieldConstant.MAX_SIZE));
        paramList.add(context.getUpdateParameter(FieldConstant.MAX_AGGR_COUNT));
        paramList.add(context.getUpdateParameter(FieldConstant.MAX_AGGR_SIZE));
        paramList.add(LocalDateTime.now());
        paramList.add(LocalDateTime.now());

        return new MapperResult(sql, paramList);

    }
}
